package gov.nasa.anml.utility;

public class SimpleString implements SimpleObject<SimpleString> {

	public char[] v;
	public int length;

	public static final SimpleString Empty = new SimpleString("");
	
	public SimpleString() {
		v = new char[10];
		length = 0;
	}

	/**  Takes control of the array!
	 * capacity = v.length = length
	 */
	public SimpleString(char[] v) {
		this.v = v;
		this.length = v.length;
	}

	/**  Takes control of the array!
	 *  v.length = capacity
	 *  l <= v.length
	 */
	public SimpleString(char[] v, int l) {
		this.v = v;
		this.length = l;
	}

	// vacuum up integer arrays in order to enable hashCode and thus HashMaps
	// update: implemented ArrMap, so this isn't really necessary
	// note: but it's still useful, and raises the issue of using byte[] instead
	// (and then one would vacuum up ints in chunks of 4 and drop the high bytes
	// of chars [one hopes ASCII is represented as 0 high bytes, ascii in low byte]
	public SimpleString(int[] a) {
		int l = a.length,t;
		int j=l<<1;
		char[]v = new char[j--];
		this.v = v;
		this.length = l--;
		for(;l>=0;--l) {
			t = a[l];
			v[j--] = (char) (t<<16);
			v[j--] = (char) (t);
		}
	}

	// explicitly makes a copy, contrast with char[] constructor
	public SimpleString(SimpleString s) {
		char[]src=s.v;
		int c = src.length;
		int l = s.length;
		char[]dst = new char[c];
		System.arraycopy(src,0,dst,0,l);
		this.length = l;
		this.v = dst;
		this.hash = s.hash;
	}
	
	// makes a copy.  Inconsistent with this(char[]) and this(char[], int l)
	// in C we can use arrays like pointers and pointers like arrays
	// so we could just point into the middle -- and
	// then copying wouldn't be necessary here.
	// Java has no pointers, only references, and
	// no notion of subarrays as distinct objects that
	// can be referenced.  Sadly.
	public SimpleString(char[] src, int start, int end) {
		int l = end-start;
		char[]dst = new char[l];
		System.arraycopy(src,start,dst,0,l);
		this.length = l;
		this.v = dst;
	}

	public SimpleString(String n) {
		v = n.toCharArray();
		length = v.length;
		hash = n.hashCode();
	}

	private int hash = 0;

	public int hashCode() {
		int h = hash;
		if (h == 0) {
			int off = 0;
			char val[] = v;
			int len = length;

			for (int i = 0; i < len; i++) {
				h = 31 * h + val[off++];
			}
			hash = h;
		}
		return h;
	}
	
	// don't call this unless you know types match.
	public boolean equals(Object o) {
		return equals((SimpleString)o);
	}
	
	public boolean equals(SimpleString s) {
		if (this == s) {
			return true;
		}
		int n = length;
		if (n == s.length) {
			char v1[] = v;
			char v2[] = s.v;
			while (n-- != 0) {
				if (v1[n] != v2[n])
					return false;
			}
			return true;
		}
		return false;
	}
	
	public static int compareTo(SimpleString a, SimpleString b) {
		if (a == null)
			return 1;
		if (b == null)
			return -1;
		if (a == b)
			return 0;
		
		int n1 = a.length;
		int n2 = b.length;
		char v1[] = a.v;
		char v2[] = b.v;
		int i = 0;
		if (n1 < n2) {
			while (n1-- != 0) {
				char c1 = v1[i];
				char c2 = v2[i];
				++i;
				if (c1 != c2)
					return c1 - c2;
			}
			return -1;
		}

		if (n1 > n2) {
			while (n2-- != 0) {
				char c1 = v1[i];
				char c2 = v2[i];
				++i;
				if (c1 != c2)
					return c1 - c2;
			}
			return 1;
		}

		while (n1-- != 0) {
			char c1 = v1[i];
			char c2 = v2[i];
			++i;
			if (c1 != c2)
				return c1 - c2;
		}
		
		return 0;
	}
	
	public static final boolean equals(SimpleString a, SimpleString b) {
		if (a == null || b == null)
			return false;
		if (a == b)
			return true;
		int n = a.length;
		if (n == b.length) {
			char v1[] = a.v;
			char v2[] = b.v;
			while (n-- != 0) {
				if (v1[n] != v2[n])
					return false;
			}
			return true;
		}
		return false;
	}
	public SimpleString clone() {
		SimpleString s;
		try {
			s = (SimpleString) super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
		s.v = v.clone();
		return s;
	}

	public int compareTo(SimpleString s) {
		int n1 = length;
		int n2 = s.length;
		char v1[] = v;
		char v2[] = s.v;
		int i = 0;
		if (n1 < n2) {
			while (n1-- != 0) {
				char c1 = v1[i];
				char c2 = v2[i];
				++i;
				if (c1 != c2)
					return c1 - c2;
			}
			return -1;
		}

		if (n1 > n2) {
			while (n2-- != 0) {
				char c1 = v1[i];
				char c2 = v2[i];
				++i;
				if (c1 != c2)
					return c1 - c2;
			}
			return 1;
		}

		while (n1-- != 0) {
			char c1 = v1[i];
			char c2 = v2[i];
			++i;
			if (c1 != c2)
				return c1 - c2;
		}
		return 0;
	}

	public final int compareTo(SimpleObject<SimpleString> o) {
		return compareTo((SimpleString)o);
	}
	
	public String toString() {
		return new String(v);
	}

	public void assign(SimpleString s) {
		hash = s.hash;
		int n2 = s.length;
		char[] v = this.v;
		if (v.length < n2) {
			v = new char[n2];
			this.v = v;
		}
		System.arraycopy(s.v, 0, v, 0, n2);
		length = n2;
	}

	public void assign(String s) {
		int l = s.length();
		hash = s.hashCode();
		length = l;
		if (l > v.length) {
			v = new char[l];
		}
		s.getChars(0,l,v,0);
	}

	public SimpleString value() {
		return this;
	}
}
